﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace KingdeeWebServiceProject
{
    public static class RSACryptoService
    {
        #region 调用密钥组
        public const string privateKey = "<RSAKeyValue><Modulus>06RMD0a4j/VGHMnb6uD5jER/9ltx1woc+H8qT9Tb6iq6A01vphrm9bE4CxqoIpk4USCiD/GpCsig+IQQD8SUYzVDK+5SIFiRaAJArG98j3/3RQDtsS1iEdwD3h08N7EcopJydXU8BwAilA1Kc3XCfLfmQ4Z2SH8t0p4gDUumJFs=</Modulus><Exponent>AQAB</Exponent><P>9NQExuNjIUkLISqZdh4o+kKgkAYRMImnDb2hY3/00GwSO8jKbc0nMw4kryPqu64cLCVTZYLgeaAj7iukQediVQ==</P><Q>3UybyqJFI5EXN9WvwVPTQiyk6/8n6UeI5sOk4hUyDnXlBPbCUPD41oG2L7Qp+3u/1s0wYMRNpJYqhA15slj77w==</Q><DP>4B4J9WsIPtsXthfB/Y+kYVuGkfEL4UvRQdHaoDPtDrIviszHCfaoMKN8z1rosT+0CHFuw1koVg5Tdd47chz3NQ==</DP><DQ>3AosbhNjQ7Ykq/PhSg2bZZUWd0HB4YarbSjjbZk9qHs5OPJSzECObFuVV2GAzPmDCoYDsHP/78MQizUK6HbqKQ==</DQ><InverseQ>48JGLeY38hEBY9d50Rqhohbs6yrqINGXLNRdb7qKqQ1dCclt+2C4qOuV36tyLHZRgyae7Bwf+z4oraNVfGWvYw==</InverseQ><D>XoeL0WbtGJ+c6U7gA1DpJVWTMh42Aq5psjRaWb3hW/4ph0AXFkH91s+JEKyfXJTDKrlAqY5uynpCK74QznonLDhzPXv9d8SWn26xa5+kWZJYNDDRBJD4rW4STm/sFv9PZSXgm0Cni3mmnz+3pcnLsjwggwz7/PRCma5iP5TxyEE=</D></RSAKeyValue>";
        public const string publicKey = "<RSAKeyValue><Modulus>06RMD0a4j/VGHMnb6uD5jER/9ltx1woc+H8qT9Tb6iq6A01vphrm9bE4CxqoIpk4USCiD/GpCsig+IQQD8SUYzVDK+5SIFiRaAJArG98j3/3RQDtsS1iEdwD3h08N7EcopJydXU8BwAilA1Kc3XCfLfmQ4Z2SH8t0p4gDUumJFs=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
        #endregion
        #region 返回参数密钥组
        public const string rPrivateKey = "<RSAKeyValue><Modulus>nLY6BLXYUPNByc+eBkw3wGZyyquA6t7akoaqXm+Coyhd5ZKueBPzVxuocK6z3W8VDOsgmo4jkuixzyFyBu+z1W0JfPgHDUnkTuGCefuSZMZ//VTOPKlxkzTWC3A1uH/d5i+f2Z/pdas/OIQoLJ9i8etnet0vHBlvSIueAQrmWr0=</Modulus><Exponent>AQAB</Exponent><P>uU6xcemUc3fBHvp1tsTmui/wgn+W8pJiZadW8apz/RmNWtCYvk7BCF+bYUZ0bBYvpmabI2CFGnMJaAb6bqup7w==</P><Q>2H7ccMaf2JOwAwaXE/S/+wTEPRYL+fOwodq3Ytv5d/DJKi2QlEa1aN/qTvbi+bLEUQSUhoa7nEDCcLqGxNkiEw==</Q><DP>nJGF0faGjI05agA6p2N0gwnwT4KYOno+kx8xkdzwRYBqc7nd5KXL6VRGh4ks4wpX1mPJXrm1nKRn5TJINGvslw==</DP><DQ>oFFZRn4fko7TMXpo2BNPM0B1XVL9LWxC6aiAUsnYs/Pv07cIMHUoE3B1H2J99DBoZiKBJhmRxoTCOB44fH7aVw==</DQ><InverseQ>Q3TIP7vwXhekZ9jne+sOjGd18flSTl9MU4ryKTjy97FXZCH0i/PVoWQCSxBdxd2XOb49Au3IKHGudVN4d94nkQ==</InverseQ><D>C5sNOesTrY8OWLlI/TNoz5Vmu+6umfZOHprdhCfi911WctmFlTv5AgL42vt9M5F18CJ7pCaRqOAVxv61mKDo4vAyBJdCesh15po3phP/gTf7qNDwQ6ZzlGcG+NAzj62qFFIxLkLTzSuI7b/2/LqK1n1aumD+Wdd6hhYi8U7MmUs=</D></RSAKeyValue>";
        public const string rPublicKey = "<RSAKeyValue><Modulus>nLY6BLXYUPNByc+eBkw3wGZyyquA6t7akoaqXm+Coyhd5ZKueBPzVxuocK6z3W8VDOsgmo4jkuixzyFyBu+z1W0JfPgHDUnkTuGCefuSZMZ//VTOPKlxkzTWC3A1uH/d5i+f2Z/pdas/OIQoLJ9i8etnet0vHBlvSIueAQrmWr0=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
        #endregion
        /// 生成公钥,私钥对
        /// </summary> 
        public static string[] GenerateKeys()
        {
            string[] sKeys = new String[2];
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            sKeys[0] = rsa.ToXmlString(true);//私钥
            sKeys[1] = rsa.ToXmlString(false);//公钥
            return sKeys;
        }

        /// <summary> 
        /// RSA 加密
        /// </summary> 
        /// <param name="sSource" >明文</param> 
        /// <param name="sPublicKey" >公钥</param> 
        public static string EncryptString(string sSource, string sPublicKey)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            string plaintext = sSource;
            rsa.FromXmlString(sPublicKey);
            byte[] cipherbytes;
            byte[] byteEn = rsa.Encrypt(Encoding.UTF8.GetBytes("a"), false);
            cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(plaintext), false);

            StringBuilder sbString = new StringBuilder();
            for (int i = 0; i < cipherbytes.Length; i++)
            {
                sbString.Append(cipherbytes[i] + ",");
            }
            return sbString.ToString();
        }


        /// <summary> 
        /// RSA 解密
        /// </summary> 
        /// <param name="sSource">密文</param> 
        /// <param name="sPrivateKey">私钥</param> 
        public static string DecryptString(String sSource)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(privateKey);
            byte[] byteEn = rsa.Encrypt(Encoding.UTF8.GetBytes("a"), false);
            string[] sBytes = sSource.Split(',');

            for (int j = 0; j < sBytes.Length; j++)
            {
                if (sBytes[j] != "")
                {
                    byteEn[j] = Byte.Parse(sBytes[j]);
                }
            }
            byte[] plaintbytes = rsa.Decrypt(byteEn, false);
            return Encoding.UTF8.GetString(plaintbytes);
        }

        /// <summary>
        /// 加密 长度无限制
        /// </summary>
        /// <param name="plaintext"></param>
        /// <returns></returns>
        public static String Encrypt(this String plaintext,string strPublicKey)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(strPublicKey);
            using (RSACryptoServiceProvider RSACryptography = rsa)
            {
                Byte[] PlaintextData = Encoding.UTF8.GetBytes(plaintext);
                int MaxBlockSize = RSACryptography.KeySize / 8 - 11;    //加密块最大长度限制
                if (PlaintextData.Length <= MaxBlockSize)
                    return Convert.ToBase64String(RSACryptography.Encrypt(PlaintextData, false));
                using (MemoryStream PlaiStream = new MemoryStream(PlaintextData))
                using (MemoryStream CrypStream = new MemoryStream())
                {
                    Byte[] Buffer = new Byte[MaxBlockSize];
                    int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);

                    while (BlockSize > 0)
                    {
                        Byte[] ToEncrypt = new Byte[BlockSize];
                        Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);

                        Byte[] Cryptograph = RSACryptography.Encrypt(ToEncrypt, false);
                        CrypStream.Write(Cryptograph, 0, Cryptograph.Length);

                        BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
                    }
                    return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
                }
            }
        }

        /// <summary>
        /// 解密 长度无限制
        /// </summary>
        /// <param name="ciphertext"></param>
        /// <param name="strPrivateKey"></param>
        /// <returns></returns>
        public static String Decrypt(this String ciphertext, string strPrivateKey)
        {
            try
            {
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                rsa.FromXmlString(strPrivateKey);
                using (RSACryptoServiceProvider RSACryptography = rsa)
                {
                    string dummyData = ciphertext.Trim().Replace("%", "").Replace(",", "").Replace(" ", "+");
                    if (dummyData.Length % 4 > 0)
                    {
                        dummyData = dummyData.PadRight(dummyData.Length + 4 - dummyData.Length % 4, '=');
                    }
                    Byte[] CiphertextData = Convert.FromBase64String(dummyData);
                    int MaxBlockSize = RSACryptography.KeySize / 8;    //解密块最大长度限制

                    if (CiphertextData.Length <= MaxBlockSize)
                        return Encoding.UTF8.GetString(RSACryptography.Decrypt(CiphertextData, false));

                    using (MemoryStream CrypStream = new MemoryStream(CiphertextData))
                    using (MemoryStream PlaiStream = new MemoryStream())
                    {
                        Byte[] Buffer = new Byte[MaxBlockSize];
                        int BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);

                        while (BlockSize > 0)
                        {
                            Byte[] ToDecrypt = new Byte[BlockSize];
                            Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize);

                            Byte[] Plaintext = RSACryptography.Decrypt(ToDecrypt, false);
                            PlaiStream.Write(Plaintext, 0, Plaintext.Length);

                            BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
                        }
                        return Encoding.UTF8.GetString(PlaiStream.ToArray());
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }
    }
}
